package com.yanqu.road.entity.autodata;

import com.yanqu.road.entity.FieldTypeAnnotation;
import com.yanqu.road.utils.classutil.ClassHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class AutoActivityConfigObject {
    private static Logger logger = LogManager.getLogger(AutoActivityConfigObject.class.getName());
    private static final Map<Class<?>, AutoActivityConfigClazzInfo> autoClazzInfoMap = new HashMap<>();

    public static boolean loadAllClazzInfo() {
        try {
            Package pack = AutoActivityConfigObject.class.getPackage();
            for (Class<?> data : ClassHelper.getClasses(pack)) {
                analysisClass(data);
            }
            return true;
        } catch (Exception e) {
            logger.error("load autoconfig failure", e);
            return false;
        }
    }

    public static void analysisClass(Class<?> clazz) throws IllegalAccessException, NoSuchMethodException {
        if (!AutoActivityConfigObject.class.isAssignableFrom(clazz)) {
            return;
        }
        FieldTypeAnnotation annotation = clazz.getAnnotation(FieldTypeAnnotation.class);
        if (annotation != null) {
            initClazzInfo(clazz);
        }
    }

    private static <T> void initClazzInfo(Class<T> clazz) throws IllegalAccessException, NoSuchMethodException {
        FieldTypeAnnotation annotation = clazz.getAnnotation(FieldTypeAnnotation.class);
        if (annotation == null) {
            return;
        }
        AutoActivityConfigClazzInfo autoActivityConfigClazzInfo = new AutoActivityConfigClazzInfo();
        String tableName = annotation.tableName();

        Field[] fields = clazz.getDeclaredFields();
        Map<Field, MethodHandle> fieldMethodHandleMap = new HashMap<>();
        for (Field field : fields) {
            FieldTypeAnnotation fieldTypeAnnotation = field.getAnnotation(FieldTypeAnnotation.class);
            if (fieldTypeAnnotation == null) {
                continue;
            }
            Method setter = ClassHelper.findSetter(clazz, field);
            // 使用 MethodHandles 调用方法
            MethodHandle setterHandle = MethodHandles.lookup().unreflect(setter);
            fieldMethodHandleMap.put(field, setterHandle);
        }
        autoActivityConfigClazzInfo.setFieldSetterMethodHandleMap(fieldMethodHandleMap);
        autoActivityConfigClazzInfo.setTableName(tableName);
        Constructor<T> constructor = clazz.getConstructor();
        autoActivityConfigClazzInfo.setConstructor(constructor);

        autoClazzInfoMap.put(clazz, autoActivityConfigClazzInfo);
    }

    public static AutoActivityConfigClazzInfo getAutoActivityConfigClazzInfo(Class<?> clazz) {
        return autoClazzInfoMap.get(clazz);
    }

    public static AutoActivityConfigObject createInstance() {
        return new AutoActivityConfigObject();
    }
}
